<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>随心听</title>
  <link rel="shortcut icon" type="image/x-icon" href="favicon.ico" media="screen">
  <!-- <link href="https://cdn.bootcdn.net/ajax/libs/layui/2.9.21/css/layui.min.css" rel="stylesheet"> -->
  <link href="./css/layui.min.2.9.21.css" rel="stylesheet">
  <!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/aplayer/1.10.1/APlayer.min.css"> -->
  <link href="./css/APlayer.min.1.10.1.css" rel="stylesheet">
  <link href="./css/index.css" rel="stylesheet">
</head>

<body>
  <div class="layui-row main">
    <div class="layui-col-sm2 layui-col-xs0"> </div>
    <div class="layui-col-sm8 layui-col-xs12">

      <div class="layui-form" style="margin-bottom: 15px;">
        <input type="radio" name="hobby" value="index-2.htm" lay-skin="none" lay-filter="form-demo-skin" checked>
        <div lay-radio class="lay-skin-tag layui-badge">随机</div>
        <input type="radio" name="hobby" value="forum-1-2.htm" lay-skin="none" lay-filter="form-demo-skin">
        <div lay-radio class="lay-skin-tag layui-badge">华语</div>
        <input type="radio" name="hobby" value="forum-15-2.htm" lay-skin="none" lay-filter="form-demo-skin">
        <div lay-radio class="lay-skin-tag layui-badge">日韩</div>
        <input type="radio" name="hobby" value="forum-10-2.htm" lay-skin="none" lay-filter="form-demo-skin">
        <div lay-radio class="lay-skin-tag layui-badge">欧美</div>
        <input type="radio" name="hobby" value="forum-11-2.htm" lay-skin="none" lay-filter="form-demo-skin">
        <div lay-radio class="lay-skin-tag layui-badge">Remix</div>
        <input type="radio" name="hobby" value="forum-12-2.htm" lay-skin="none" lay-filter="form-demo-skin">
        <div lay-radio class="lay-skin-tag layui-badge">纯音乐</div>
        <input type="radio" name="hobby" value="forum-13-2.htm" lay-skin="none" lay-filter="form-demo-skin">
        <div lay-radio class="lay-skin-tag layui-badge">异次元</div>
        <input type="radio" name="hobby" value="forum-17-2.htm" lay-skin="none" lay-filter="form-demo-skin">
        <div lay-radio class="lay-skin-tag layui-badge">特供</div>
      </div>

      <form class="layui-form" action="script:;">
        <div class="layui-form-item">
          <div class="layui-input-group" style="width: 100%;">
            <input id="search" name="search" type="text" placeholder="搜搜歌曲" class="layui-input">
            <div class="layui-input-split layui-input-suffix" lay-submit lay-filter="demo1" style="cursor: pointer;">
              <i class="layui-icon layui-icon-search"></i>
            </div>
          </div>
        </div>
      </form>

      <table class="layui-hide" id="ID-table-demo-data"></table>

      <div id="aplayer" style="margin:15px 0;"></div>

      <div class="layui-card">
        <div class="layui-card-header">歌词</div>
        <div class="layui-card-body" id="lrc">
          我期待,<br>
          有一天我会回来,<br>
          回到我最初的爱,<br>
          回到童贞的神采;<br>
        </div>
      </div>

      <hr class="layui-border-green">
      <!-- <blockquote class="layui-elem-quote" style="background-color: #ddede5;">
        <i class="layui-icon layui-icon-question" style="font-size: 19px; color: #17a682;"></i>
        为什么有音乐列表但不能播放音乐？这是歌源网站已暂时限制该网络，请切换网络或重启飞行模式后刷新网页
      </blockquote> -->
      <blockquote class="layui-elem-quote" style="background-color: #ddede5;">
        截至当前访问总次数：<em id="call_count"></em><br>
        截至当前播放歌曲总次数：<em id="call_music_count"></em><br>
      </blockquote>
      <blockquote class="layui-elem-quote" style="background-color: #ddede5;">
        本项目将持续优化，欢迎您的反馈，可以通过邮件 1227297881@qq.com 提交您宝贵的意见。项目创始于2025-02-08.
      </blockquote>

    </div>
    <div class="layui-col-sm2 layui-col-xs0"> </div>

    <!-- 播放音源，需要这个hifini网站打开刷新一下记录才行。不需要了，因为在服务器把重定向的请求给解决了，直接获取到最终的音源地址，和hifini关系不大了，所以这个hifini网站同步加载就取消了。 -->
    <!-- <iframe src="https://hifini.com" style="display: none;" frameborder="0" id="myiframe"></iframe> -->
  </div>

  <script src="./js/APlayer.min.1.10.1.js"></script>
  <script src="./js/layui.min.2.9.21.js"></script>
  <script src="./js/axios.js"></script>
  <script type="text/html" id="toolDemo">
    <div class="layui-clear-space"   style="display: flex; justify-content: center;">
      <button type="button" class="layui-btn layui-btn-xs" onclick="window.open('{{= d.musicInfoUrl }}')">打开</button>
      <button type="button" class="layui-btn layui-btn-xs" onclick="download('{{= d.musicInfoUrl }}')">下载</button>
    </div>
  </script>
  <script>
    // 播放音源，需要这个hifini网站打开刷新一下记录才行。
    // let newwin = window.open('https://hifini.com/thread-112767.htm', 'hifini');
    // setTimeout(() => { newwin.close() }, 500);

    let lrc = document.getElementById('lrc');
    let ap; // 播放器
    var loadIndex; // 加载层的返回值
    let rowCheckedIndex = 0; // 记录点击列表的索引
    let getMusicInfo; // 获取歌曲信息
    let musicType = ''; // 获取哪种类型的音乐，比如华语，日韩等
    let playErrorMount = 0; // 记录连续播放失败次数
    let curUrll = ''; // 记录当前播放的歌源网址

    // 保存歌曲列表信息
    let musicData = [/* { "name": "人间就我这一款", "artist": "红小乐", "musicInfoUrl": "https://hifini.com/thread-315739.htm" } */]

    // 点击下载按钮
    function download(d) {
      getMusicInfo(d, true);
    }

    layui.use(function () {
      var layer = layui.layer;
      var form = layui.form;
      var table = layui.table;
      var util = layui.util;

      // 单选事件
      form.on('radio(form-demo-skin)', function (data) {
        var elem = data.elem; // 获得 radio 原始 DOM 对象
        var value = elem.value; // 获得 radio 值
        musicType = value;
        updateMusic({});
        localStorage.setItem('mt', value);
      });
      musicType = localStorage.getItem('mt') || 'index-2.htm';
      document.querySelector(`[name="hobby"][value="${musicType}"] ~ div`).click();

      // 提交事件
      form.on('submit(demo1)', function (data) {
        var field = data.field; // 获取表单字段值
        updateMusic(field)
        return false; // 阻止默认 form 跳转
      });
      document.getElementById('search').addEventListener('keydown', function (event) {
        if (event.key === 'Enter' || event.keyCode === 13) {
          event.preventDefault();
          updateMusic({ search: event.target.value });
        }
      });

      // 已知数据渲染
      var inst = table.render({
        elem: '#ID-table-demo-data',
        cols: [[ //标题栏
          { field: 'name', title: '歌曲', minWidth: 170 },
          { field: 'artist', title: '歌手', minWidth: 120 },
          { field: 'musicInfoUrl', title: '歌源地址', minWidth: 280 },
          { field: 'download', title: '操作', minWidth: 90,/* fixed: 'right', */ templet: '#toolDemo' },
        ]],
        data: [ /* { "name": "10228", "artist": "张三8", "musicInfoUrl": "", "download": "qqq", } */],
      });
      // 行单击事件
      table.on('row(ID-table-demo-data)', function (obj) {
        if (obj.e.target.type == "button") return; //  var e = obj.e; // 当前的 jQuery 事件对象 --- 2.9.14+
        // var dataCache = obj.dataCache; // 得到当前行缓存数据，包含特定字段 --- 2.8.8+
        // var tr = obj.tr; // 得到当前行 <tr> 元素的 jQuery 对象
        // var options = obj.config; // 获取当前表格基础属性配置项
        var data = obj.data; // 得到当前行数据
        rowCheckedIndex = obj.index; // 得到当前行索引
        getMusicInfo(data.musicInfoUrl);
        // obj.update(fields, related);  // 修改行数据
        obj.setRowChecked({ type: 'radio' }); // 设置行选中状态
      });

      /**   
       * 更新列表，搜搜或随机歌曲
       * @url hifini网站的地址
       * @search
       * @refreshEndExe {Function} 在更新列表后执行的方法
       */
      function updateMusic({ url = '', search = '', refreshEndExe = Function }) {
        let u = './get_music/php/getmusiclist.php';
        if (search.trim()) u += '?search=' + search;
        else u += '?url=' + (url || 'https://hifini.com/' + musicType);
        loadIndex = layer.load(0); // 加载层
        axios.get(u)
          .then(function (response) {
            if (response.data.length > 0) {
              musicData = response.data;
              let reloadData = [];
              musicData.forEach((item) => {
                item.name = item.name.replace(/<\/?em>/g, '');
                item.artist = item.artist.replace(/<\/?em>/g, '');
                reloadData.push(item)
              })
              table.reloadData('ID-table-demo-data', { data: reloadData });
              rowCheckedIndex = 0;
              refreshEndExe && refreshEndExe(); // 在更新列表后执行的方法
            } else {
              layer.msg('没有搜搜到目标歌曲');
            }
            layer.close(loadIndex); // 取消加载层
          })
          .catch(function (error) {
            layer.close(loadIndex); // 取消加载层
            layer.msg('搜搜或随机歌曲遇到未知错误');
          });
      }
      // updateMusic({});

      // 获取歌曲信息
      getMusicInfo = function (url, isDownload = false) {
        if (!url) { alert('没有目标地址'); return };
        let u = './get_music/php/getmusicinfo.php?url=' + url;
        loadIndex = layer.load(0); // 加载层  
        curUrll = url;
        axios.get(u)
          .then(function (response) {
            let d = response.data;
            if (d.verificationFail) { verificationFail(); layer.close(loadIndex); return; }
            if (!d.url) { setTimeout(() => { autoNextPlay(); }, 3000); layer.close(loadIndex); return; }
            if (isDownload) { window.open(d.url); layer.close(loadIndex); return; } // 直接下载，不播放。
            try { // 删除原有歌曲信息，添加新的并播放
              ap.list.remove(0);
              ap.list.add([d]);
              ap.list.switch(0);
              ap.play();
            } catch (error) { }
            setMusicTip(d.lyric);
            call_music_count_fun();
            layer.close(loadIndex); // 取消加载层  
          })
          .catch(function (error) {
            layer.close(loadIndex); // 取消加载层
            layer.msg('没有找到该歌曲的音源！');
          });
      }

      // 自动播放下一首
      function autoNextPlay() {
        // 判断是不是列表里面的最后一首，是则刷新列表。
        if (musicData.length - 1 <= rowCheckedIndex) {
          updateMusic({
            refreshEndExe: () => {
              getMusicInfo(musicData[rowCheckedIndex].musicInfoUrl);
              table.setRowChecked('ID-table-demo-data', { type: 'radio', index: rowCheckedIndex });
            }
          });
        } else {// 不是最后一首，则播放自动播放下一首
          table.setRowChecked('ID-table-demo-data', { type: 'radio', index: ++rowCheckedIndex }); // 设置行选中状态
          getMusicInfo(musicData[rowCheckedIndex].musicInfoUrl);
        }
      }

      // 设置歌曲的歌词
      function setMusicTip(lyric = []) { lrc.innerHTML = lyric.join('<br>'); }

      ap = new APlayer({ container: document.getElementById('aplayer'), loop: 'none', audio: [] });

      // 监听播放结束
      ap.on('ended', function () {
        autoNextPlay(); playErrorMount = 0;
      });

      // 播放错误
      ap.on('error', function () {
        layer.msg('该歌曲遇到未知错误，自动播放下一首');
        console.log('player error');
        if (++playErrorMount >= 3) ap.pause();
        else { /* document.getElementById('myiframe').src = curUrll; */ setTimeout(() => { autoNextPlay(); }, 3000);
        }
      });

      // 播放开始
      ap.on('play', function () { console.log('player play'); });

      /* 处理人机认证失败的流程  start*/
      // 认证的cookis失效了
      function verificationFail() {
        verification = layer.open({
          type: 1,
          title: 'Cookie认证失效，需要重置Cookie',
          // area: ['420px', '240px'], // 宽高
          content: `
            <div style="margin: 10px;">
              <button type="button" class="layui-btn layui-btn-primary" onclick='verificationFun()'>开始重置认证Cookie</button>
              <a href="./verification" target="_blank" style='color:#089184;' rel="noopener noreferrer">怎么做？看这里</a>
            </div>`,
        });
      }
      // 设置cookie中tac_tmp字段的值
      verificationFun = function () {
        layer.close(verification);
        layer.prompt({ title: '请输入Cookie中tac_tmp字段的值' }, function (value, index, elem) {
          if (value === '') return elem.focus();
          loadIndex = layer.load(0); // 加载层 
          axios.get(`./get_music/php/config.php?type=set&content=${util.escape(value)}`)
            .then(function (response) {
              let d = response.data;
              if (d = value) layer.msg('重置Cookie中tac_tmp字段的值===>成功');
              else layer.msg('重置Cookie中tac_tmp字段的值===>失败');
              layer.close(loadIndex); // 取消加载层  
            })
            .catch(function (error) {
              layer.close(loadIndex); // 取消加载层
              layer.msg('重置Cookie中tac_tmp字段的值===>失败2');
            });
          // 关闭 prompt
          layer.close(index);
        });
      }
      /* 处理人机认证失败的流程  end*/

      // 获取截至今日访问总次数
      function call_count_fun() {
        axios.get('./get_music/php/call_count.php')
          .then(function (response) { document.getElementById('call_count').innerText = response?.data || 0; })
          .catch(function (error) { });
      };
      call_count_fun();
      // 截至今日播放歌曲总次数
      function call_music_count_fun() {
        axios.get('./get_music/php/call_music_count.php')
          .then(function (response) { document.getElementById('call_music_count').innerText = response?.data || 0; })
          .catch(function (error) { });
      };
      call_music_count_fun();

    });
  </script>
</body>

</html>